import { base16Encode } from "./base16";
import { warning } from "./toast";
import { UserProfile } from "./userProfile";

export const foundClass = "find";
export function newRegExp(pattern?: string, flags?: string): RegExp | null {
    let result = null
    try {
        if (!!pattern && pattern.endsWith('\\') && !pattern.endsWith('\\\\')) pattern += '\\';
        result = pattern ? new RegExp(pattern, flags) : null;
    } catch (e: any) {
        warning(e.toString());
    }
    return result;
}



let beepSound: HTMLMediaElement | undefined;
export function beep() {
    if (!beepSound) {
        beepSound = new Audio('/sound/beep.wav');
    }
    try {
        beepSound.pause();
        beepSound.currentTime = 0;
        beepSound.play();
    } catch (e) {
        console.log(e);
    }
}

let woooSound: HTMLMediaElement | undefined;
export function wooo() {
    console.log("wooo called");
    if (!woooSound) {
        woooSound = new Audio('/sound/wooo.wav');
    }
    try {
        woooSound.pause();
        woooSound.currentTime = 0;
        woooSound.play();
    } catch (e) {
        console.log(e);
    }
}

let dongSound: HTMLMediaElement | undefined;
export function dong() {
    console.log("dong called");
    if (!dongSound) {
        dongSound = new Audio('/sound/dong.mp3');
    }
    try {
        dongSound.pause();
        dongSound.currentTime = 0;
        dongSound.play();
    } catch (e) {
        console.log(e);
    }
}



let ringSound: HTMLMediaElement | undefined;
export function ring() {
    if (!ringSound) {
        ringSound = new Audio('/sound/ring.wav');
    }
    try {
        ringSound.pause();
        ringSound.currentTime = 0;
        ringSound.play();
    } catch (e) {
        console.log(e);
    }
}

export function fineParams(params: object, userProfile?: UserProfile): object {
    return userProfile ? {
        operName: userProfile.userName,
        operId: userProfile.userId,
        cors: userProfile.dataUrlPrefix,
        ...params
    } : params;
}

export async function fetchJson(url: string): Promise<any> {
    url += "?r=" + Math.random();
    return await fetchData(url, true);
}

export async function fetchText(url: string): Promise<string> {
    url += "?r=" + Math.random();
    return await fetchData(url, false);
}


async function fetchData(url: string, retJson: boolean = true, init?: RequestInit): Promise<any> {
    try {
        let response = await fetch(url, init);
        return await (retJson ? response.json() : response.text());
    } catch (e) {
        const msg = "fetch " + url + "出错:" + JSON.stringify(e);
        warning(msg);
        if (retJson)
            return { msg }
        else
            return `{msg:"${msg}"}`
    }
}
export async function fetchAskData(ask: string, params: object, retJson: boolean = true, userProfile?: UserProfile): Promise<any> {
    const dataUrlPrefix = (userProfile && userProfile.dataUrlPrefix) ? userProfile.dataUrlPrefix : "";
    const paramsStr = JSON.stringify(fineParams(params, userProfile));
    const init = dataUrlPrefix ? { mode: "cors" as RequestMode } : undefined;
    const qs = "?ask=" + ask + "&params=" + base16Encode(paramsStr);
    return await fetchData(dataUrlPrefix + "/api/ask" + qs, retJson, init);
}

export async function fetchActData(act: string, params: object, retJson: boolean = true, userProfile?: UserProfile): Promise<any> {
    const dataUrlPrefix = (userProfile && userProfile.dataUrlPrefix) ? userProfile.dataUrlPrefix : "";
    const paramsStr = JSON.stringify(fineParams(params, userProfile));
    const init: RequestInit = {
        method: "POST",
        headers: { 'content-type': 'application/x-www-form-urlencoded' },
        body: "act=" + act + "&params=" + base16Encode(paramsStr)
    };
    if (dataUrlPrefix) init.mode = "cors" as RequestMode;

    return await fetchData(dataUrlPrefix + "/api/act", retJson, init);
}

export function createLookup<K extends string | number | symbol, V, T>
    (list: T[], eachAct: (lookup: Record<K, V>, x: T) => void): Record<K, V> {
    let lookup: Record<K, V> = {} as Record<K, V>;
    list.forEach(x => eachAct(lookup, x));
    return lookup;
}

export function saveTextToFile(text: string, fileName: string, triggerDelay: number = 200, removeDelay: number = 1000 * 2) {
    const url = 'data:text/plain;charset=utf-8,' + text;
    downloadFile(url, fileName, triggerDelay, removeDelay);
}

/// fileUrl  为文件网址
/// fileName 保存的文件名
/// 必须同源才能下载
export function downloadFile(fileUrl: string, fileName: string = "", triggerDelay: number = 200, removeDelay: number = 1000 * 60) {
    setTimeout(function () {
        const a: HTMLAnchorElement = document.createElement("a");
        a.style.display = "none"; // 防止影响页面
        a.style.height = "0"; // 防止影响页面
        a.href = fileUrl;
        a.download = fileName;
        a.click();
        document.body.appendChild(a);
        setTimeout(() => document.body.removeChild(a), removeDelay);
    }, triggerDelay);
}

export function sleep(second: number) {
    return new Promise((resolve) => setTimeout(resolve, second * 1000));
}



export function deepClone(obj: any) {
    let newObj: any = Array.isArray(obj) ? [] : {}
    if (obj && typeof obj === "object") {
        for (let key in obj) {
            if (obj.hasOwnProperty(key)) {
                newObj[key] = (obj && typeof obj[key] === 'object') ? deepClone(obj[key]) : obj[key];
            }
        }
    }
    return newObj
}